<?php
/**
 * エラー処理クラス
 * 
 * 1.0 2010.11.20 初期リリース
 * 
 * @filesource Error.class.php
 * @package forty-two
 * @subpackage forty-two
 * @version 1.0
 */

// +------------------------------------------------------------------------
// | エラークラス
// +------------------------------------------------------------------------
// エラーに関する設定の読み込み
require_once 'error.conf.php';



// フレームワーク以外で利用の場合、必要定数を定義
if (!defined('__FRAMEWORK') || __FRAMEWORK != 'forty-two') {
    // PHP標準定数「DIRECTORY_SEPARATOR」のエイリアス定数DS未定義時
    if (!defined('DS')) {
        define('DS', DIRECTORY_SEPARATOR);
    }
    // 改行定数BR未定義時
    if (!defined('BR')) {
        define('BR', "\n");
    }
    // 定数PATH_ROOTが定義されているか確認。
    if (!defined('PATH_ROOT')) {
        define('PATH_ROOT', '');
    }
    // デバッグモード(詳細表示：TRUE / 表示しない：FALSE)
    if (!defined('DEBUG_MODE')) {
        define('DEBUG_MODE', TRUE);
    }
    // エラー時のエラー内容メール送信先
    if (!defined('ERROR_REPORTING_MAIL_TO')) {
        define('ERROR_REPORTING_MAIL_TO', '');
    }
    // エラー時にトレースする階層設定(整数以外は全て出力します)
    if (!defined('DEBUG_DISP_TRACE_HIERARCHY')) {
         define('DEBUG_DISP_TRACE_HIERARCHY', 'infinity');
    }
    
    // エラー時に出力する該当箇所前後行数設定(整数以外は前後5行出力します)
    if(!defined('DEBUG_DISP_ERROR_SOURCE')) {
         define('DEBUG_DISP_ERROR_SOURCE', 5);
    }
    // error_reportingの設定、基本はE_ALL
    if(!defined('DEBUG_DISP_ERROR_SOURCE')) {
        define('ERROR_REPORTING_LEVEL', E_ALL);
    }
}



/**
 * エラークラス
 * 
 * 1.0 2010.11.20 初期リリース
 * 
 * @author koto
 * @package forty-two
 * @version 1.0
 */
class Error
{
    
    /**
     * ファクトリーメソッド
     *
     * エラーオブジェクトのインスタンスを作成します。
     * また、頻繁に呼び出される可能性があるので、メモリ削減と速度向上のために、
     * オブジェクトをグローバルで保持しポインタを返します。
     * 
     * @since 1.0
     * @static
     * @access public
     * @return object
     */
    static function & factory()
    {
        // 既に定義済みの場合は既存オブジェクトを返す
        if (isset($GLOBALS['forty-two']['Error']['obj'])
             && is_object($GLOBALS['forty-two']['Error']['obj'])
        ) {
            return $GLOBALS['forty-two']['Error']['obj'];
        } else {
            // 自分を実体化
            $obj =& new Error();
            $GLOBALS['forty-two']['Error']['obj'] = $obj;
            return $GLOBALS['forty-two']['Error']['obj'];
        }
        
        return FALSE;
    }
    
    
    
    /**
     * エラーハンドラ
     * 
     * エラー時発生時の振る舞いの定義
     * 
     * @static
     * @access public
     * @param integer $errorNo       エラーコード
     * @param string  $errorMess     エラーメッセージ
     * @param string  $errorFilePath エラーファイル名
     * @param integer $errorLine     エラー発生した行数番号
     * @param array   $vars          エラー発生した際のスコープに含まれている変数
     * @return void
     */
    function handler ($errorNo, $errorMess, $errorFilePath, $errorLine, $vars)
    {
        // PHPエラーレポートレベル配列取得
        $errorLevelArrays = Error::_getErrorReportingLevel();
        
        // 今回のエラーコード取得
        $errorType = isset($errorLevelArrays[$errorNo]['code'])?$errorLevelArrays[$errorNo]['code']:'';
        
        // ファイル名のみ抽出
        $errorFile = basename($errorFilePath);
        
        
        // デバッグモードの確認
        if (defined('DEBUG_MODE') && is_bool(constant('DEBUG_MODE')) && DEBUG_MODE)
        {
            // デバッグモード：TRUE
            // 詳細なエラーレポートを表示
            Error::_detailErrorReporting($errorType, $errorMess, $errorFilePath, $errorFile, $errorLine, $vars);
        }
        else
        {
            // デバッグモード：FALSE
            // 簡易なエラーレポートを表示
            $dispErrorMess = sprintf('<p><b>%s</b> %s(%s) %s</p>', $errorType, $errorFile, $errorLine, $errorMess);
            
            echo $dispErrorMess;
            
            // エラー内容をメールで送信します。
            Error::_errorSendMail($errorType, $errorMess, $errorFilePath, $errorFile, $errorLine, $vars);
        }
        
        // ログ書き出し処理
        Error::_errorLoging($errorType, $errorMess, $errorFilePath, $errorFile, $errorLine, $vars);
    }
    
    
    
    /**
     * エラーメール送信処理
     * 
     * エラー内容をメールにて送信します。
     * 
     * @static
     * @access public
     * @param string  $errorType     エラーコード
     * @param string  $errorMess     エラーメッセージ
     * @param string  $errorFilePath エラーファイル名フルパス
     * @param string  $errorFile     エラーファイル名
     * @param integer $errorLine     エラー発生した行数番号
     * @param array   $vars          エラー発生した際のスコープに含まれている変数
     * @return void
     */
    function _errorSendMail(&$errorType, &$errorMess, &$errorFilePath, &$errorFile, &$errorLine, &$vars)
    {
        // エラー内容をメールで送信
        if (defined('ERROR_REPORTING_MAIL_TO') && strlen(ERROR_REPORTING_MAIL_TO) > 5)
        {
            $arg = count(Error::_varsCatch($vars))>0?Error::_varsCatch($vars):'&nbsp;';
            $arg = (strlen($arg)<=(1024*10))?$arg:mb_strimwidth($arg,0,100,'…');
            
            $arg2 = count(Error::_varsCatch(debug_backtrace()))>0?Error::_varsCatch(debug_backtrace()):'&nbsp;';
            $arg2 = (strlen($arg2)<=(1024*10))?$arg2:mb_strimwidth($arg2,0,100,'…');
            
            // 書き出すログ生成(日時は自動で先頭に付加されます)
            $errorMessage =  'Error Time : ' . date('Y-m-d H:i:s') . BR;
            $errorMessage .= 'Error Type : ' . $errorType . BR;
            $errorMessage .= 'Error File : ' . $errorFilePath . '(' . $errorLine . ')' . BR;
            $errorMessage .= 'Error Mess : ' . $errorMess . BR;
            $errorMessage .= 'Error Vars : ' . BR;
            $errorMessage .= BR;
            $errorMessage .= $arg;
            $errorMessage .= BR;
            $errorMessage .= $arg2;
            
            // 定義時
            error_log($errorMessage, 1, ERROR_REPORTING_MAIL_TO);
        }
    }
    
    
    
    /**
     * エラーロギング処理
     * 
     * エラー内容をログファイルに書き出します。
     * 
     * @static
     * @access public
     * @param string  $errorType     エラーコード
     * @param string  $errorMess     エラーメッセージ
     * @param string  $errorFilePath エラーファイル名フルパス
     * @param string  $errorFile     エラーファイル名
     * @param integer $errorLine     エラー発生した行数番号
     * @param array   $vars          エラー発生した際のスコープに含まれている変数
     * @return void
     */
    function _errorLoging(&$errorType, &$errorMess, &$errorFilePath, &$errorFile, &$errorLine, &$vars)
    {
        
        // 書き出すログ生成(日時は自動で先頭に付加されます)
        $errorMessage = $errorType;
        $errorMessage .= ' : ' . $errorFilePath . '(' . $errorLine . ')';
        $errorMessage .= ' : ' . $errorMess;
        
        // ログファイルへ書き出し
        error_log($errorMessage, 0);
    }
    
    
    
    /**
     * 詳細エラーレポート
     * 
     * 詳細なエラーのレポートを行います。
     * 
     * @static
     * @access public
     * @param string  $errorType     エラーコード
     * @param string  $errorMess     エラーメッセージ
     * @param string  $errorFilePath エラーファイル名フルパス
     * @param string  $errorFile     エラーファイル名
     * @param integer $errorLine     エラー発生した行数番号
     * @param array   $vars          エラー発生した際のスコープに含まれている変数
     * @return void
     */
    function _detailErrorReporting(&$errorType, &$errorMess, &$errorFilePath, &$errorFile, &$errorLine, &$vars)
    {
        // トーレス階層定義確認
        if (defined('DEBUG_DISP_TRACE_HIERARCHY')
         && is_int(DEBUG_DISP_TRACE_HIERARCHY)
         && DEBUG_DISP_TRACE_HIERARCHY > 0
        ) {
            // 設定有効時
            $debugDispTraceHierarchy = DEBUG_DISP_TRACE_HIERARCHY;
        }
        else
        {
            // 設定無効時
            $debugDispTraceHierarchy = 'infinity';
        }
        
        // エラーソース出力行数定義確認
        if (defined('DEBUG_DISP_ERROR_SOURCE')
         && is_int(DEBUG_DISP_ERROR_SOURCE)
         && DEBUG_DISP_ERROR_SOURCE > 0
        ) {
            // 設定有効時
            $debugDispErrorSource = DEBUG_DISP_ERROR_SOURCE;
        }
        else
        {
            // 設定無効時
            $debugDispErrorSource = 5;
        }
        
        // メモリ使用量の取得
        $errorRes = Error::_getErrorResource();
        
        // トレースデータの取得
        $traceData = Error::_getTraceData($debugDispTraceHierarchy);
        
        // エラーファイル内容表示処理
        $errorFileSauceData = Error::_getErrorSauce($errorFilePath, $errorLine, $debugDispErrorSource);
        
        $css = ' style=\'border-style:none;color:#FFFFFF;background-color:#999999;border:solid 1px #000000;\'';
        
        // エラー基本情報 HTML化
        $errorFilePathShort = $errorFilePath;
        if (strlen(PATH_ROOT)>0) {
            $errorFilePathShort = ereg_replace(dirname(PATH_ROOT) . DS, '', $errorFilePath);
        }
        $errorBaseData = sprintf('<p><b>%s</b> %s(%s) %s</p>', $errorType, $errorFilePathShort, $errorLine, $errorMess);
        
        // トレース情報ラベル定義
        $traceDataHTML = '<tr><td'.$css.'>No</td><td'.$css.'>file</td><td'.$css.'>function</td><td'.$css.'>arg</td></tr>';
        
        // エラートレース情報 HTML化
        foreach ($traceData as $key => $value)
        {
            $tmp = join('</td><td'.$css.'>', $value);
            $traceDataHTML .= '<tr><td'.$css.'>' . $tmp . '</td></tr>' . BR;
        }
        if (count($traceData)<=0) {
            $traceDataHTML = '';
        }
        
        // エラーファイルソース HTML化
        $errorFileSauceData = ereg_replace('<br>$', '', $errorFileSauceData);
        $errorFileSauceData = ereg_replace('<code>|</code>', '', $errorFileSauceData);
        $errorFileSauceDataHTML = '<tr><td colspan=\'4\''.$css.'><pre>' . $errorFileSauceData . '</td></pre></tr>';
        
        // メモリ使用量 HTML化
        if (isset($errorRes['now'])) {
            $errorResNowHTML  = '<tr><td colspan=\'1\''.$css.' align=\'center\'>now use memory.</td><td colspan=\'3\''.$css.'>%s(%s)</td></tr>';
            $errorResHTML[] = vsprintf($errorResNowHTML, $errorRes['now']);
        }
        if (isset($errorRes['max'])) {
            $errorResMaxHTML = '<tr><td colspan=\'1\''.$css.' align=\'center\'>max use memory.</td><td colspan=\'3\''.$css.'>%s(%s)</td></tr>';
            $errorResHTML[] = vsprintf($errorResMaxHTML, $errorRes['max']);
        }
        $errorResHTML = join('', $errorResHTML);
        
        $runTime = '-';
        if (class_exists('CU')) {
            $runTime = CU::getExecTime();
        }
        
        // 全エラー情報結合
        $detailErrorReportingHTML  = '<table border=\'0\''.$css.'>';
        $detailErrorReportingHTML .= '<tr><td colspan=\'4\''.$css.'>' . $errorBaseData . '</td></tr>';
        $detailErrorReportingHTML .= '<tr><td colspan=\'1\''.$css.' align=\'center\'>now datetime.</td><td colspan=\'3\''.$css.'>'.date('Y/m/d H:i:s').'</td></tr>';
        $detailErrorReportingHTML .= '<tr><td colspan=\'1\''.$css.' align=\'center\'>run time.</td><td colspan=\'3\''.$css.'>'.$runTime.'</td></tr>';
        $detailErrorReportingHTML .= $errorResHTML;
        $detailErrorReportingHTML .= $errorFileSauceDataHTML;
        $detailErrorReportingHTML .= $traceDataHTML;
        $detailErrorReportingHTML .= '</table>';
        
        // 表示
        echo $detailErrorReportingHTML;
    }
    
    
    
    /**
     * メモリ使用量取得処理
     * 
     * メモリの使用量を取得します。
     * 
     * @static
     * @access private
     * @return string | string
     */
    function _getErrorResource()
    {
        /**
         * PHP 5.2以降か、PHP5 を 「--enable-memory-limit」 オプション付きでコンパイルする必要あり
         */
        if (function_exists('memory_get_usage')) {
            // 現在のメモリ使用量(論理使用量)
            $mem['now']['logical'] = ERROR::_convertNum(memory_get_usage(FALSE));
            // 現在のメモリ使用量(物理使用量)
            $mem['now']['physics'] = ERROR::_convertNum(memory_get_usage(TRUE));
        }
        if (function_exists('memory_get_peak_usage')) {
            // 最大メモリ使用量(論理使用量)
            $mem['max']['logical'] = ERROR::_convertNum(memory_get_peak_usage(FALSE));
            // 最大メモリ使用量(物理使用量)
            $mem['max']['physics'] = ERROR::_convertNum(memory_get_peak_usage(TRUE));
        }
        
        return $mem;
    }
    
    
    
    function _convertNum($num = 0)
    {
        if ($num < 1024) {
            return $num.'byte';
        } else if ($num < 1048576) {
            return round($num/1024,3).'KB';
        } else {
            return round($num/1048576,3).'MB';
        }
    }
    
    function _numReturnBytes($val) {
        $val = trim($val);
        $last = strtolower($val[strlen($val)-1]);
        $last = ($last=='b')?strtolower($val[strlen($val)-2]):$last;
        switch($last) {
            // 'G' は PHP 5.1.0 以降で使用可能です
            case 'g':
                $val *= 1024;
            case 'm':
                $val *= 1024;
            case 'k':
                $val *= 1024;
        }
        
        return $val;
    }
    
    
    
    /**
     * エラー発生箇所ソース取得処理
     * 
     * エラーが発生したソースファイルのエラー該当行前後指定行のソースを取得します。
     * 
     * @static
     * @access private
     * @param string   $filePath     対象ファイルへのパス
     * @param int      $errorLineNo  エラー行の指定
     * @param int      $dispLineNo   前後何行取得するか指定(未定時は5)
     * @return string | boolean
     */
    function _getErrorSauce($filePath = '', $errorLineNo = '' ,$dispLineNo = 5)
    {
        // 引数チェック
        if (!is_readable($filePath) || !is_int($errorLineNo))
        {
            return FALSE;
        }
        
        // エラーファイル内容表示処理
        $sauceData = file($filePath);
        
        if (!isset($sauceData) || !is_array($sauceData))
        {
            return FALSE;
        }
        
        // 出力データ保持用変数の初期化
        $str = '';
        
        // 出力開始行の初期化処理
        $fast = (($errorLineNo-$dispLineNo)>=0)?($errorLineNo-$dispLineNo):0;
        
        // 出力処理(条件式で$1に+1しているのは配列が0スタートなのを補正する為)
        for ($i = $fast; $i+1 <=$errorLineNo+$dispLineNo;$i++)
        {
            // 該当行のデータが存在するか
            if(isset($sauceData[$i]))
            {
                // ソースのハイライト処理
                $sauce = $sauceData[$i];
                $sauce = (ereg('[/\*]+', $sauce))?ereg_replace('/\*', '******', $sauce):$sauce;
                $sauce = highlight_string($sauce, TRUE);
                $sauce = ereg_replace("[\r|\r\n|\n]", '', $sauce);
                $sauce = (ereg('[/\*]+', $sauceData[$i]))?ereg_replace('\*\*\*\*\*\*', '/*', $sauce):$sauce;
                
                // 出力ファイル内容整形($1に+1しているのは配列が0スタートなのを補正する為)
                $str .= ($i+1 ==$errorLineNo)?'&gt;':'&nbsp;';
                $str .= sprintf('%04d',$i+1).'|';
                $str .= ($i+1 ==$errorLineNo)?sprintf('<b>%s</b>', $sauce):$sauce;
            }
        }
        return trim($str);
    }
    
    
    
    /**
     * エラートレース情報取得処理
     * 
     * エラーが発生した際のトレース情報を取得します。
     * 
     * @static
     * @access private
     * @param int      $dispTraceNo   何階層までトレース情報を取得するか指定(未定時は0)
     * @return array | boolean
     */
    function _getTraceData($dispTraceNo = 0)
    {
        // 定数PATH_ROOTが定義されているか確認。
        if (!defined('PATH_ROOT'))
        {
            // 定義されていない場合はフルパス表示。
            define('PATH_ROOT','');
        }
        
        // トレース情報の取得
        $dbt = debug_backtrace();
        
        // ループ内利用変数の初期化
        $traceData = array();
        $errorClassNum = 0;
        $type = array('file', 'line', 'class', 'type', 'function', 'args');
        foreach ($dbt as $key => $value)
        {
            // 表示階層設定になれば表示終了
            if ($dispTraceNo != 0 && $dispTraceNo == (($key)-$errorClassNum))
            {
                break;
            }
            
            // 配列初期化処理
            foreach ($type as $k => $v)
            {
                $value[$v] = isset($value[$v])?$value[$v]:'';
            }
            
            // エラークラスに関しては出力しない
            if ($value['class']!=__CLASS__)
            {
                $passClass = array('UT');
                if (in_array($value['class'], $passClass)) {
                    // 出力ファイル名の簡略化
                    if (PATH_ROOT!='') {
                        $value['file'] = ereg_replace(dirname(PATH_ROOT).DS, '', $value['file']);
                    }
                    $arg = count(Error::_varsCatch($value['args']))>0?Error::_varsCatch($value['args']):'&nbsp;';
                    $maxLengs = 2000;
                    $arg = (mb_strlen($arg)<=$maxLengs)?htmlspecialchars($arg):htmlspecialchars(mb_strimwidth($arg,0,$maxLengs,'...省略されました...'));
                    
                    // テーブル化
                    $traceData[] = array(
                                     (($key+1) - $errorClassNum)
                                    ,$value['file'] . '(' . $value['line'] . ')'
                                    ,$value['class'] . $value['type'] . $value['function'] . '()'
                                    ,sprintf('<pre>%s</pre>', $arg)
                                );
                }
            } else {
                // エラークラス出現回数をカウント
                $errorClassNum += 1;
            }
        }
        
        // トレース情報を戻す
        return $traceData;
    }
    
    
    
    /**
     * PHPエラーレポートレベル配列取得関数
     * 
     * PHPのエラーレポートレベルに関する情報を配列で返します。
     * 
     * @static
     * @access private
     * @return array
     */
    function _getErrorReportingLevel()
    {
        return array(
             '' => array(
                 'code' => ''
                ,'type' => ''
                ,'mess' => ''
                ,'etc'  => ''
            )
            ,defined('E_ERROR')?E_ERROR:'E_ERROR'
              => array(
                 'code' => 'E_ERROR'
                ,'type' => 'E_ERROR(integer)'
                ,'mess' => '重大な実行時エラー。これは、メモリ確保に関する問題のように復帰できないエラーを示します。スクリプトの実行は中断されます。'
                ,'etc'  => '&nbsp;'
            )
            ,defined('E_WARNING')?E_WARNING:'E_WARNING'
            => array(
                 'code' => 'E_WARNING'
                ,'type' => 'E_WARNING(integer)'
                ,'mess' => '実行時の警告 (致命的なエラーではない)。スクリプトの実行は中断されません。'
                ,'etc'  => '&nbsp;'
            )
            ,defined('E_PARSE')?E_PARSE:'E_PARSE'
            => array(
                 'code' => 'E_PARSE'
                ,'type' => 'E_PARSE(integer)'
                ,'mess' => 'コンパイル時のパースエラー。パースエラーはパーサでのみ生成されます。'
                ,'etc'  => '&nbsp;'
            )
            ,defined('E_NOTICE')?E_NOTICE:'E_NOTICE'
            => array(
                 'code' => 'E_NOTICE'
                ,'type' => 'E_NOTICE(integer)'
                ,'mess' => '実行時の警告。エラーを発しうる状況に遭遇したことを示す。ただし通常のスクリプト実行の場合にもこの警告を発することがありうる。'
                ,'etc'  => '&nbsp;'
            )
            ,defined('E_CORE_ERROR')?E_CORE_ERROR:'E_CORE_ERROR'
            => array(
                 'code' => 'E_CORE_ERROR'
                ,'type' => 'E_CORE_ERROR(integer)'
                ,'mess' => 'PHPの初期始動時点での致命的なエラー。<b>E_ERROR</b>に似ているがPHPのコアによって発行される点が違う。'
                ,'etc'  => 'PHP4より'
            )
            ,defined('E_CORE_WARNING')?E_CORE_WARNING:'E_CORE_WARNING'
            => array(
                 'code' => 'E_CORE_WARNING'
                ,'type' => 'E_CORE_WARNING(integer)'
                ,'mess' => '(致命的ではない)警告。PHPの初期始動時に発生する。<b>E_WARNING</b>に似ているがPHPのコアによって発行される 点が違う。'
                ,'etc'  => 'PHP4より'
            )
            ,defined('E_COMPILE_ERROR')?E_COMPILE_ERROR:'E_COMPILE_ERROR'
            => array(
                'code'  => 'E_COMPILE_ERROR'
                ,'type' => 'E_COMPILE_ERROR(integer)'
                ,'mess' => 'コンパイル時の致命的なエラー。<b>E_ERROR</b>に似ているがZendスクリプティングエンジンによって発行される点が違う。'
                ,'etc'  => 'PHP4より'
            )
            ,defined('E_COMPILE_WARNING')?E_COMPILE_WARNING:'E_COMPILE_WARNING'
            => array(
                 'code' => 'E_COMPILE_WARNING'
                ,'type' => 'E_COMPILE_WARNING(integer)'
                ,'mess' => 'コンパイル時の警告(致命的ではない)。<b>E_WARNING</b>に似ているがZendスクリプティングエンジンによって発行される点が違う。'
                ,'etc'  => 'PHP4より'
            )
            ,defined('E_USER_ERROR')?E_USER_ERROR:'E_USER_ERROR'
            => array(
                 'code' => 'E_USER_ERROR'
                ,'type' => 'E_USER_ERROR(integer)'
                ,'mess' => 'ユーザーによって発行されるエラーメッセージ。<B>E_ERROR</B>に似ているがPHPコード上で<b>trigger_error()</b>関数を使用した場合に発行される点が違う。'
                ,'etc'  => 'PHP4より'
            )
            ,defined('E_USER_WARNING')?E_USER_WARNING:'E_USER_WARNING'
            => array(
                 'code' => 'E_USER_WARNING'
                ,'type' => 'E_USER_WARNING(integer)'
                ,'mess' => 'ユーザーによって発行される警告メッセージ。<b>E_WARNING</b>に似ているがPHPコード上で<b>trigger_error()</b>関数を使用した場合に発行される点が違う。'
                ,'etc'  => 'PHP4より'
            )
            ,defined('E_USER_NOTICE')?E_USER_NOTICE:'E_USER_NOTICE'
            => array(
                 'code' => 'E_USER_NOTICE'
                ,'type' => 'E_USER_NOTICE(integer)'
                ,'mess' => 'ユーザーによって発行される注意メッセージ。<b>E_NOTICE</b>に似ているがPHPコード上で<b>trigger_error()</b>関数を使用した場合に発行される点が違う。'
                ,'etc'  => 'PHP4より'
            )
            ,defined('E_STRICT')?E_STRICT:'E_STRICT'
            => array(
                 'code' => 'E_STRICT'
                ,'type' => 'E_STRICT(integer)'
                ,'mess' => '実行時の注意。コードの相互運用性や互換性を維持するためにPHPがコードの変更を提案する。'
                ,'etc'  => 'PHP5より'
            )
            ,defined('E_RECOVERABLE_ERROR')?E_RECOVERABLE_ERROR:'E_RECOVERABLE_ERROR'
            => array(
                 'code' => 'E_RECOVERABLE_ERROR'
                ,'type' => 'E_RECOVERABLE_ERROR(integer)'
                ,'mess' => 'キャッチできる致命的なエラー。危険なエラーが発生したが、エンジンが不安定な状態になるほどではないことを表す。ユーザ定義のハンドラでエラーがキャッチされなかった場合(<b>set_error_handler()</b>も参照ください)は、<b>E_ERROR</b>として異常終了する。'
                ,'etc'  => 'PHP5.2より'
            )
            ,defined('E_ALL')?E_ALL:'E_ALL'
            => array(
                 'code' => 'E_ALL'
                ,'type' => 'E_ALL(integer)'
                ,'mess' => 'サポートされる全てのエラーと警告。PHP&lt;6では<b>E_STRICT</b>レベルのエラーは除く。'
                ,'etc'  => 'PHP5.2では6143、それより前のバージョンでは2047でした。'
            )
        );
    }
    
    
    
    /**
     * 変数文字列化処理
     * 
     * 変数の値を文字列として返します。
     * 
     * @static
     * @access private
     * @param ???   $vars     文字列化したい変数
     * @return void
     */
    function _varsCatch(&$vars)
    {
        // 引数が指定されているか確認
        if(!(isset($vars) && ((is_string($vars) && strlen($vars) > 0) || (is_array($vars) && count($vars) > 0))))
        {
            return FALSE;
        }
        
        // 値の取得
        ob_start();
        var_dump($vars);
        $buf =& ob_get_contents();
        ob_end_clean();
        
        // 文字列化した変数を戻す
        return $buf;
    }
    
    
    
    
    
    
    /**
     * フレームワーク内エラー処理開始
     * 
     * 各種エラーを標準出力しないようにします。
     * 
     * @static
     * @access private
     * @return void
     */
    function fwLibBegin()
    {
        $this->beginOn = TRUE;
        
        $this->_display_errors = ini_get('display_errors');
        if (version_compare(phpversion(), '5.2.4', '>')) {
            ini_set('display_errors', 'stderr');
        } else {
            ini_set('display_errors', FALSE);
        }
        
        $this->_error_handler = set_error_handler(create_function('$errno,$errstr', 'return false;'));
        
        return TRUE;
    }
    
    
    
    
    
    
    /**
     * フレームワーク内エラー処理開始
     * 
     * 各種エラーを標準出力しないようにします。
     * 
     * @static
     * @access private
     * @return void
     */
    function fwLibEnd()
    {
        if (!isset($this->beginOn) || $this->beginOn !== TRUE) {
            return FALSE;
        }
        if (version_compare(phpversion(), '5.2.4', '>')) {
            ini_set('display_errors', $this->_display_errors);
        } else {
            ini_set('display_errors', $this->_display_errors);
        }
        
        set_error_handler($this->_error_handler);
//        restore_error_handler();
        
        return TRUE;
    }
}
?>